package org.deng.learn.basic.nio.socket;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

/**
 * @author DengLibin
 * @Description nio socket 客户端
 * @Date 2019/2/25 0025 17:12
 */
public class NioClient {

    //通道管理器
    private Selector selector;

    public NioClient(String serverIp, int port) throws IOException {
        //获取socket通道
        SocketChannel channel = SocketChannel.open();
        //非阻塞
        channel.configureBlocking(false);
        //获得通道管理器
        selector=Selector.open();
        //客户端连接服务器，需要调用channel.finishConnect();才能实际完成连接。
        channel.connect(new InetSocketAddress(serverIp, port));
        //为该通道注册SelectionKey.OP_CONNECT事件
        channel.register(selector, SelectionKey.OP_CONNECT);
    }

    public  void listen() throws IOException {
        System.out.println("客户端启动");
        //轮询访问selector
        while (true){
            //选择注册过的io操作的事件(第一次为SelectionKey.OP_CONNECT)
            selector.select(); //阻塞 直到有事件到达
            Iterator<SelectionKey> ite = selector.selectedKeys().iterator();
            while (ite.hasNext()){
                SelectionKey key = ite.next();
                //删除已选的key，防止重复处理
                ite.remove();
                if(key.isConnectable()){
                    System.out.println("客户端连接成功");
                    SocketChannel channel=(SocketChannel)key.channel();

                    //如果正在连接，则完成连接
                    if(channel.isConnectionPending()){
                        channel.finishConnect();
                    }

                    channel.configureBlocking(false);
                    //向服务器发送消息
                    channel.write(ByteBuffer.wrap(new String("send message to server.").getBytes()));

                    //连接成功后，注册接收服务器消息的事件
                    channel.register(selector, SelectionKey.OP_READ);
                }else if(key.isReadable()){
                    SocketChannel channel = (SocketChannel)key.channel();

                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    int read = channel.read(buffer);
                    if(read <= 0){
                        System.out.println("server disconnected");
                        key.cancel();
                        return;
                    }
                    byte[] data = buffer.array();
                    String message = new String(data, 0, buffer.position());

                    System.out.println("receive message from server:, size:" + buffer.position() + " msg: " + message);
                }
            }
        }
    }
    public  static  void main(String[] args) throws IOException {
        NioClient nioClient = new NioClient("127.0.0.1",10250);
        nioClient.listen();
    }

}
